using System;
using Flaschengeist.Entities;

namespace Flaschengeist.Processes 
{
	public class CalculateLevelScore
	{		
		private const float bonusFactorFluid = 0.2f;
		private const float bonusFactorTime = 1.7f;
		private const int bonusCorrectNote = 100;
		private const int bonusRelatedNote = 25;
		
		public void Process(LevelResult result)
		{
			result.RemainingFluidScore = (int)(Math.Floor(result.RemainingFluid * bonusFactorFluid));
			result.RemainingTimeScore = (int)(Math.Floor(result.RemainingTimeSec * bonusFactorTime));			
			
			for (int i = 0; i < result.Track.Length; i++) 
			{
				if (result.Track[i] == result.LevelTrack[i])
				{
					result.CorrectNotes++;
					result.CorrectNotesScore += bonusCorrectNote;
				}
				else if (isNoteSimilar(result.Scale, result.Track[i], result.LevelTrack[i]))
				{
					result.SimilarNotes++;
					result.SimilarNotesScore += bonusRelatedNote;
				}
			}
			
			// Score für alle Noten richtig
			var allNotesCorrectScore = result.Track.Length * bonusCorrectNote;
			// 4 Sekunden pro Glas
			var perfectTimeScore = (int)(Math.Floor((result.TotalTimeSec - (result.Track.Length * 4)) * bonusFactorTime));
			// in Abhänigkeit von der Scale minimale Menge die notwendig wäre um Melodie zu spielen
			var perfectFluidScore = (int)(Math.Floor((double)(result.TotalFluid - ((result.MaxFillLevel/result.Scale.Length) * result.Track.Length)) * bonusFactorFluid)); 
			
			result.MaxScore = allNotesCorrectScore + perfectTimeScore + perfectFluidScore;
			result.Score = result.CorrectNotesScore + result.SimilarNotesScore + result.RemainingFluidScore + result.RemainingTimeScore;					
			Completed(result);
		}

		private bool isNoteSimilar(string[] scale, string trackNote, string levelNote)
		{
			var relatedUpperNote = string.Empty;
			var relatedLowerNote = string.Empty;
			
			for (int i = 0; i < scale.Length; i++) 
			{
				if (scale[i] == levelNote)
				{
					if (i == 0)
					{
						relatedUpperNote = scale[i + 1];
						break;
					}
					else if (i == scale.Length-1)
					{
						relatedLowerNote = scale[i - 1];
						break;
					}
					else
					{
						relatedUpperNote = scale[i + 1];
						relatedLowerNote = scale[i - 1];
					}				
				}
			}
			return relatedUpperNote == trackNote || relatedLowerNote == trackNote;
		}
		
		public event Action<LevelResult> Completed;
	}
}


